# -*- encoding: utf-8 -*-

from app import models
from django.contrib.auth.models import User
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def avg(lista):
    suma = 0.0
    for elem in lista:
        suma += elem
    avg = suma/len(lista)*1.0
    return round(avg,1)

def valoracion(pelicula):
    if models.Valoraciones.objects.filter(pelicula_id=pelicula).count():
        pelicula_valoraciones = models.Valoraciones.objects.filter(pelicula_id=pelicula)
        notas = []
        for val in pelicula_valoraciones:
            notas.append(val.valoracion)
        return avg(notas)
    else:
        return "No hay valoraciones"
    
def sim(a,b):
    sum1 = 0
    sum2 = 0
    sum3 = 0
    
    peliculas_db = models.Peliculas.objects.all()
    peliculas_votadas_por_ambos = []
    
    for pelicula in peliculas_db:
        if models.Valoraciones.objects.filter(usuario_id=a,pelicula_id=pelicula.id).count() and models.Valoraciones.objects.filter(usuario_id=b,pelicula_id=pelicula.id).count():
            peliculas_votadas_por_ambos.append(pelicula)
    
    va_lista = []
    vb_lista = []
    
    for pelicula in peliculas_votadas_por_ambos:
        nota_a = models.Valoraciones.objects.get(usuario_id=a,pelicula_id=pelicula.id)
        nota_b = models.Valoraciones.objects.get(usuario_id=b,pelicula_id=pelicula.id)
        va_lista.append(nota_a.valoracion)
        vb_lista.append(nota_b.valoracion)
        
    va = avg(va_lista)
    vb = avg(vb_lista)
    
    for pelicula in peliculas_votadas_por_ambos:
        va_p = models.Valoraciones.objects.get(usuario_id=a,pelicula_id=pelicula.id)
        va_p_val = va_p.valoracion
        vb_p = models.Valoraciones.objects.get(usuario_id=b,pelicula_id=pelicula.id)
        vb_p_val = vb_p.valoracion
        sum1 += (va_p_val-va)*(vb_p_val-vb)
        sum2 += (va_p_val-va)**2
        sum3 += (vb_p_val-vb)**2
    if (sum2**0.5)*(sum3**0.5) == 0:
        res = -1
    else:
        res = sum1/((sum2**0.5)*(sum3**0.5))
    return res

def vecindario(user_id):
    similitudes = []
    usuarios_con_votos = []
    for usuario in User.objects.all().exclude(id=user_id):
        if models.Valoraciones.objects.filter(usuario_id=usuario.id).count():
            usuarios_con_votos.append(usuario)
    for usuario_b in usuarios_con_votos:
        similitudes.append((usuario_b,sim(user_id,usuario_b.id)))
    res = []
    for user2,similitud in similitudes:
        if similitud > 0.0:
            res.append((user2,similitud))
    return res

def pred(a_id,p, vecinos):
    
    va_lista = []
    
    #vecinos = vecindario(a_id)
    sum1 = 0.0
    sum2 = 0.0
    
    for v in models.Valoraciones.objects.filter(usuario_id=a_id):
        nota_a = models.Valoraciones.objects.get(usuario_id=a_id,pelicula_id=v.pelicula_id)
        va_lista.append(nota_a.valoracion)
    
    va = avg(va_lista)
    
    for vecino,similitud in vecinos:
        vb_lista = []
        for v in models.Valoraciones.objects.filter(usuario_id=vecino.id):
            vb_lista.append(v.valoracion)
        vb = avg(vb_lista)
        if models.Valoraciones.objects.filter(usuario_id=vecino.id,pelicula_id=p.id):
            vbp = models.Valoraciones.objects.get(usuario_id=vecino.id,pelicula_id=p.id)
            sum1 += sim(a_id,vecino.id)*(vbp.valoracion-vb)
        sum2 += sim(a_id,vecino.id)
    
    res = va + sum1/sum2
    
    return res

def paginador(lista, pagina):
    
    paginator = Paginator(lista, 5) # Muestra 5 elementos por página

    try:
        paginacion = paginator.page(pagina)
    except PageNotAnInteger:
        # Si página no es un entero, mostrar primera página.
        paginacion = paginator.page(1)
    except EmptyPage:
        # Si página fuera de rango (ej. 9999), mostrar última página.
        paginacion = paginator.page(paginator.num_pages)
    return paginacion
    